package com.cbh.amadeus.server.utils;

import com.cbh.amadeus.common.protocol.AmadeusMessage;
import com.cbh.amadeus.common.utils.StringPool;
import com.cbh.amadeus.server.domain.ChannelModel;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author ChenBiHui
 * @date 2025/4/25
 */
@Slf4j
public final class TopicChannelManage {

    private static final Map<Channel, ChannelModel> CHANNEL_WITH_MODEL = new ConcurrentHashMap<>(64);
    private static final Map<String, List<ChannelModel>> TOPIC_WITH_MODEL = new ConcurrentHashMap<>(64);

    public static ChannelModel findModelWithChannel(Channel channel) {
        return CHANNEL_WITH_MODEL.get(channel);
    }

    public static List<ChannelModel> findModelWithTopic(String topic) {
        return TOPIC_WITH_MODEL.get(topic);
    }

    public static void set(Channel channel, AmadeusMessage message) {
        String provider = message.getProvider();
        String topic = message.getTopic();
        ChannelModel channelModel = CHANNEL_WITH_MODEL.computeIfAbsent(
                channel,
                k -> new ChannelModel(channel, provider)
        );
        channelModel.getTopics().add(topic);
        List<ChannelModel> channelModels = TOPIC_WITH_MODEL.computeIfAbsent(
                topic,
                k -> new CopyOnWriteArrayList<>()
        );
        if (!channelModels.contains(channelModel)) {
            try {
                channelModel.getLock().lock();
                if (!channelModels.contains(channelModel)) {
                    channelModels.add(channelModel);
                }
            } finally {
                channelModel.getLock().unlock();
            }
        }
    }

    public static void remove(Channel channel) {
        ChannelModel channelModel = CHANNEL_WITH_MODEL.remove(channel);
        if (channelModel == null) {
            return;
        }
        String name = channelModel.getName();
        for (String topic : channelModel.getTopics()) {
            List<ChannelModel> channelModels = TOPIC_WITH_MODEL.get(topic);
            if (channelModels == null) {
                continue;
            }
            channelModels.remove(channelModel);
            log.info(
                    "===== Topic [{}] of the channel has been release with [{}]-[{}] =====",
                    topic,
                    name,
                    channel.remoteAddress()
            );
            if (channelModels.isEmpty()) {
                log.info(
                        "===== Topic [{}] of the channels list is empty =====",
                        topic
                );
            }
        }
    }

    public static String origin(String name) {
        if (name.contains(StringPool.DASH)) {
            return name.substring(0, name.lastIndexOf(StringPool.DASH));
        }
        return name;
    }
}
